#include "Sock.hpp"
#include <string>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>

#define NUM (sizeof(fd_set) * 8)

static void Usage(std::string proc)
{
    std::cout << "Usage: " << std::endl;
    std::cout << "      " << proc << " port" << std::endl;
}

static void SetNonBlock(int fd)
{
    int fl = fcntl(fd, F_GETFL);
    if(fl == -1)
    {
        fprintf(stderr, "fcntl: %s\n", strerror(errno));
    }

    fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}


int main(int argc, char* argv[])
{ 
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(2);
    }

    int listen_sock = Sock::Socket();
    Sock::Bind(listen_sock, atoi(argv[1]));
    Sock::Listen(listen_sock); 

    // 初始化fd_array
    int fd_array[NUM];
    for(int i = 0; i < (int)NUM; ++i)
    {
       fd_array[i] = -1;
    }
    // 插入监听套接字
    fd_array[0] = listen_sock;

    // 读事件
    fd_set read_fd;

    while(true)
    {
       // 每次都要设置关心事件
       FD_ZERO(&read_fd);
       int max_fd = fd_array[0];
       for(int i = 0; i < (int)NUM; ++i)
       {
           if(fd_array[i] != -1)
           {
               FD_SET(fd_array[i], &read_fd);
           }
           if(fd_array[i] > max_fd)
           {
               max_fd = fd_array[i];
           }
       }

       // 取出关心时间
       // 设置deadline
       struct timeval* timeout = nullptr;
       int n = select(max_fd + 1, &read_fd, nullptr, nullptr, timeout);
       switch(n)
       {
           case -1:
               fprintf(stderr, "select: %s\n", strerror(errno));
               sleep(3);
               break;
           case 0:
               fprintf(stdout, "Time out!\n");
               break;
           default:
               for(int i = 0; i < (int)NUM;  ++i)
               {
                   if(fd_array[i] != -1)
                   {
                       if(FD_ISSET(fd_array[i], &read_fd))
                       {
                           // 表示当前事件发生
                           // 判断是否是连接事件
                           if(fd_array[i] == listen_sock)
                           {
                               // 连接事件
                               // std::cout << "有新链接到来!" << std::endl;
                               struct sockaddr_in peer;
                               bzero(&peer, sizeof(peer));
                               socklen_t len = sizeof(peer);
                               int fd = accept(listen_sock, reinterpret_cast<struct sockaddr*>(&peer), &len);
                               if(fd == -1)
                               {
                                   fprintf(stderr, "accept: %s\n", strerror(errno));
                               }
                               
                               // 添加到fd_array中
                               int i = 0;
                               for(i = 0; i < (int)NUM; ++i)
                               {
                                   if(fd_array[i] == -1)
                                   {
                                       fd_array[i] = fd;
                                       break;
                                   }
                               }
                               if(i == 0)
                               {
                                   fprintf(stdout, "服务器已经满载!\n");
                                   close(fd);
                                   continue;
                               }
                               
                               // 添加成功
                               // std::cout << "新连接添加成功!" << std::endl;
                           }
                           else
                           {
                               // 普通读事件到来
                               // std::cout << "普通读事件到来!" << std::endl;
                               char out_buffer[1024];
                               ssize_t s = read(fd_array[i], out_buffer, sizeof(out_buffer) - 1);
                               if(s == 0)
                               {
                                   std::cout << "对端关闭连接!" << std::endl;
                                   sleep(3);
                                   close(fd_array[i]);
                                   fd_array[i] = -1;
                               }
                               else if(s < 0)
                               {
                                   // 错误发生
                                   fprintf(stderr, "read: %s\n", strerror(errno));
                                   sleep(3);
                                   close(fd_array[i]);
                                   fd_array[i] = -1;
                               }
                               else
                               {
                                   // 有换行符存在
                                   out_buffer[s - 1] = '\0';
                                   std::cout << "Client[" << fd_array[i] << "]#: " << out_buffer << std::endl;
                               }
                           }
                           
                       }
                   }
               }
               break;
       }
    }
    

    return 0;
}
